package com.jcvision.mms.dao;

import java.lang.reflect.Method;
import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;

import com.jcvision.mms.util.PageBean;
import com.jcvision.mms.util.ResourceManager;

public abstract class BaseDao {

	protected SqlSession session = null;
	
	protected abstract Class<?> getMapperClass();
	
	protected abstract Class<?> getModelClass();
	
	protected abstract Class<?> getExampleClass();
	
	protected Object getMapper(){
		if(session != null){
			return session.getMapper(getMapperClass());
		}
		return null;
	}
	
	protected void openSession() {
		session = ResourceManager.openSession();
	}
	
	protected void commit() {
		if(session != null){
			session.commit();
		}
	}
	
	protected void closeSession() {
		ResourceManager.closeSession(session);
	}
	
	public int insert(Object record) throws Exception{
		openSession();
		int count = 0;
		try{
			Object mapper = getMapper();
			Method method = mapper.getClass().getMethod("insert", getModelClass());
			count = (int)method.invoke(mapper, record);
			commit();
		}finally{
			closeSession();
		}
		return count;
	}
	
	public List<?> select(){
		openSession();
		List<?> list = null;
		try{
			Object mapper = getMapper();
			Method method = mapper.getClass().getMethod("selectByExample", getExampleClass());
			list = (List<?>)method.invoke(mapper, new Object[]{null});
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			closeSession();
		}
		return list;
	}
	
	public Object select(Long id){
		openSession();
		Object row = null;
		try{
			Object mapper = getMapper();
			Method method = mapper.getClass().getMethod("selectByPrimaryKey", Long.class);
			row = method.invoke(mapper, id);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			closeSession();
		}
		return row;
	}
	
	public List<?> select(Object example){
		openSession();
		List<?> rows = null;
		try{
			Object mapper = getMapper();
			Method method = null;
			try{
				method = mapper.getClass().getMethod("selectByExampleWithBLOBs", getExampleClass());
			}catch(NoSuchMethodException e){
				method = mapper.getClass().getMethod("selectByExample", getExampleClass());
			}
			rows = (List<?>)method.invoke(mapper, example);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			closeSession();
		}
		return rows;
	}
	
	public List<?> select(Object example, PageBean pageBean) throws Exception {
		openSession();
		List<?> rows = null;
		int count = 0;
		try{
			Object mapper = getMapper();
			Method method = mapper.getClass().getMethod("countByExample", getExampleClass());
			count = (int) method.invoke(mapper, example);
			pageBean.setTotalRows(count);
			RowBounds rowBounds = new RowBounds(pageBean.getOffset(), pageBean.getRowsPPage());
			try{
				method = mapper.getClass().getMethod("selectByExampleWithBLOBs", getExampleClass());
			}catch(NoSuchMethodException e){
				method = mapper.getClass().getMethod("selectByExample", getExampleClass());
			}
			rows = this.session.selectList(getMapperClass().getName() + "." + method.getName(), example, rowBounds);
		}finally{
			closeSession();
		}
		return rows;
	}
	
	public int count(Object example){
		openSession();
		int count = -1;
		try{
			Object mapper = getMapper();
			Method method = mapper.getClass().getMethod("countByExample", getExampleClass());
			count = (int)method.invoke(mapper, example);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			closeSession();
		}
		return count;
	}
	
	public int update(Object record){
		openSession();
		int count = 0;
		try{
			Object mapper = getMapper();
			Method method = null;
			try{
				method = mapper.getClass().getMethod("updateByPrimaryKeyWithBLOBs", getModelClass());
			}catch(NoSuchMethodException e){
				method = mapper.getClass().getMethod("updateByPrimaryKey", getModelClass());
			}
			count = (int)method.invoke(mapper, record);
			commit();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			closeSession();
		}
		return count;
	}
	
	public int updateByPrimaryKeySelective(Object record) throws Exception {
		openSession();
		int count = 0;
		try{
			Object mapper = getMapper();
			Method method = mapper.getClass().getMethod("updateByPrimaryKeySelective", getModelClass());
			count = (int)method.invoke(mapper, record);
			commit();
		}finally{
			closeSession();
		}
		return count;
	}
	
	public int delete(Long id){
		openSession();
		int count = 0;
		try{
			Object mapper = getMapper();
			Method method = null;
			method = mapper.getClass().getMethod("deleteByPrimaryKey", Long.class);
			count = (int)method.invoke(mapper, id);
			commit();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			closeSession();
		}
		return count;
	}
	
}
